package cn.qiao.dubbo.provider.util;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;

/**
 * desc:
 * 泛化调用的工具类
 * @author qiao
 * @date 2023年07月17日 22:07
 */
public class GeneralizeUtil {

    public static Object send(String interfaceName, String method,String[] type, Object[] args ){
        //创建ApplicationConfig
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("generic-call-consumer");
        //创建注册中心配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("nacos://127.0.0.1:8848");
        // 配置分组信息, 该分组是 nacos中的分组名称 通过在配置文件中配置: 例如src/main/resources/application.yml 默认是 DEFAULT_GROUP
        registryConfig.setGroup("dubbo");
        //创建服务引用配置
        ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>();
        //设置接口
        referenceConfig.setInterface(interfaceName);
        //创建业务分组, 该分组信息通过java代码中的 @DubboService(group = "1") 生成
        referenceConfig.setGroup("");
        applicationConfig.setRegistry(registryConfig);
        referenceConfig.setApplication(applicationConfig);
        //重点：设置为泛化调用
        //注：不再推荐使用参数为布尔值的setGeneric函数
        //应该使用referenceConfig.setGeneric("true")代替
        referenceConfig.setGeneric(true);
        //设置异步，不必须，根据业务而定。
        referenceConfig.setAsync(false);
        //设置超时时间
        referenceConfig.setTimeout(7000);

        //获取服务，由于是泛化调用，所以获取的一定是GenericService类型
        GenericService genericService = referenceConfig.get();
        //使用GenericService类对象的$invoke方法可以代替原方法使用
        //第一个参数是需要调用的方法名
        //第二个参数是需要调用的方法的参数类型数组，为String数组，里面存入参数的全类名。
        //第三个参数是需要调用的方法的参数数组，为Object数组，里面存入需要的参数。
        Object result = genericService.$invoke(method,type, args);
        //使用CountDownLatch，如果使用同步调用则不需要这么做。
        //todo referenceConfig.setAsync(true) 获取结果----> 在异步调用时返回参数的获取还有问题
//        CompletableFuture<String> future = RpcContext.getContext().getCompletableFuture();
//        future.whenComplete((value, t) -> {
//            System.err.println("invokeSayHello(whenComplete): " + value);
//        });
        //打印结果
        System.err.println("invokeSayHello(return): " + result);
        return result;
    }

}
